home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevpdft.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  42.7 KB  |  1,450 lines

  1. /* Copyright (C) 1996, 2000 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevpdft.c,v 1.16 2000/09/19 19:00:17 lpd Exp $ */
  20. /* Text handling for PDF-writing driver. */
  21. #include "math_.h"
  22. #include "memory_.h"
  23. #include "string_.h"
  24. #include "gx.h"
  25. #include "gserrors.h"
  26. #include "gsmatrix.h"
  27. #include "gsutil.h"        /* for bytes_compare */
  28. #include "gxfixed.h"        /* for gxfcache.h */
  29. #include "gxfont.h"
  30. #include "gxfont0.h"
  31. #include "gxfont1.h"
  32. #include "gxfont42.h"
  33. #include "gxfcache.h"        /* for orig_fonts list */
  34. #include "gxfcid.h"
  35. #include "gxpath.h"        /* for getting current point */
  36. #include "gdevpdfx.h"
  37. #include "gdevpdff.h"
  38. #include "gdevpdfg.h"
  39. #include "scommon.h"
  40.  
  41. /*
  42.  * The PDF documentation does a pretty shoddy job of specifying use of fonts
  43.  * beyond the base 14, and on top of that, Acrobat Reader has some serious
  44.  * bugs.  Specifically, Acrobat Reader 3's Print function has a bug that
  45.  * make re-encoded characters print as blank if the font is substituted (not
  46.  * embedded or one of the base 14).
  47.  *
  48.  * We do have to handle re-encoded Type 1 fonts, because TeX output makes
  49.  * constant use of them.  We have several alternatives for how to handle
  50.  * characters whose encoding doesn't match their encoding in the base font's
  51.  * built-in encoding.  If a character's glyph doesn't match the character's
  52.  * glyph in the encoding built up so far, we check if the font has that
  53.  * glyph at all; if not, we fall back to a bitmap.  Otherwise, we use one or
  54.  * both of the following algorithms:
  55.  *
  56.  *      1. If this is the first time a character at this position has been
  57.  *      seen, assign its glyph to that position in the encoding.
  58.  *      We do this step if the device parameter ReAssignCharacters is true.
  59.  *      (This is the default.)
  60.  *
  61.  *      2. If the glyph is present in the encoding at some other position,
  62.  *      substitute that position for the character; otherwise, assign the
  63.  *      glyph to an unoccupied (.notdef) position.
  64.  *      We do this step if the device parameter ReEncodeCharacters is true.
  65.  *      (This is the default.)
  66.  *
  67.  *      3. Finally, fall back to using a bitmap.
  68.  *
  69.  * If it is essential that all strings in the output contain exactly the
  70.  * same character codes as the input, set ReEncodeCharacters to false.  If
  71.  * it is important that strings be searchable, but some non-searchable
  72.  * strings can be tolerated, the defaults are appropriate.  If searchability
  73.  * is not important, set ReAssignCharacters to false.
  74.  * 
  75.  * Since the chars_used bit vector keeps track of characters by their
  76.  * position in the Encoding, not by their glyph identifier, it can't record
  77.  * use of unencoded characters.  Therefore, if we ever use an unencoded
  78.  * character in an embedded font, we force writing the entire font rather
  79.  * than a subset.  This is inelegant but (for the moment) too awkward to
  80.  * fix.
  81.  *
  82.  * Because of the AR3 printing bug, if CompatibilityLevel <= 1.2, for
  83.  * non-embedded non-base fonts, no substitutions or re-encodings are allowed.
  84.  */
  85.  
  86. /* Forward references */
  87. private int pdf_set_font_and_size(P3(gx_device_pdf * pdev, pdf_font_t * font,
  88.                      floatp size));
  89. private int pdf_set_text_matrix(P2(gx_device_pdf * pdev,
  90.                    const gs_matrix * pmat));
  91. private int pdf_append_chars(P3(gx_device_pdf * pdev, const byte * str,
  92.                 uint size));
  93.  
  94. /* Define the text enumerator. */
  95. typedef struct pdf_text_enum_s {
  96.     gs_text_enum_common;
  97.     gs_text_enum_t *pte_default;
  98.     gs_fixed_point origin;
  99. } pdf_text_enum_t;
  100. extern_st(st_gs_text_enum);
  101. gs_private_st_suffix_add1(st_pdf_text_enum, pdf_text_enum_t, "pdf_text_enum_t",
  102.   pdf_text_enum_enum_ptrs, pdf_text_enum_reloc_ptrs, st_gs_text_enum,
  103.   pte_default);
  104.  
  105. /*
  106.  * Define quantities derived from the current font and CTM, used within
  107.  * the text processing loop.
  108.  */
  109. typedef struct pdf_text_process_state_s {
  110.     float chars;        /* scaled character spacing (Tc) */
  111.     float words;        /* scaled word spacing (Tw) */
  112.     float size;            /* font size for Tf */
  113.     gs_matrix text_matrix;    /* normalized FontMatrix * CTM for Tm */
  114.     pdf_font_t *pdfont;
  115. } pdf_text_process_state_t;
  116.  
  117. /* Define the auxiliary procedures for text processing. */
  118. private int
  119. pdf_text_resync(gs_text_enum_t *pte, const gs_text_enum_t *pfrom)
  120. {
  121.     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
  122.  
  123.     if ((pte->text.operation ^ pfrom->text.operation) & ~TEXT_FROM_ANY)
  124.     return_error(gs_error_rangecheck);
  125.     if (penum->pte_default) {
  126.     int code = gs_text_resync(penum->pte_default, pfrom);
  127.  
  128.     if (code < 0)
  129.         return code;
  130.     }
  131.     pte->text = pfrom->text;
  132.     gs_text_enum_copy_dynamic(pte, pfrom, false);
  133.     return 0;
  134. }
  135. private bool
  136. pdf_text_is_width_only(const gs_text_enum_t *pte)
  137. {
  138.     const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
  139.  
  140.     if (penum->pte_default)
  141.     return gs_text_is_width_only(penum->pte_default);
  142.     return false;
  143. }
  144. private int
  145. pdf_text_current_width(const gs_text_enum_t *pte, gs_point *pwidth)
  146. {
  147.     const pdf_text_enum_t *const penum = (const pdf_text_enum_t *)pte;
  148.  
  149.     if (penum->pte_default)
  150.     return gs_text_current_width(penum->pte_default, pwidth);
  151.     return_error(gs_error_rangecheck); /* can't happen */
  152. }
  153. private int
  154. pdf_text_set_cache(gs_text_enum_t *pte, const double *pw,
  155.            gs_text_cache_control_t control)
  156. {
  157.     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
  158.  
  159.     if (penum->pte_default)
  160.     return gs_text_set_cache(penum->pte_default, pw, control);
  161.     return_error(gs_error_rangecheck); /* can't happen */
  162. }
  163. private int
  164. pdf_text_retry(gs_text_enum_t *pte)
  165. {
  166.     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
  167.  
  168.     if (penum->pte_default)
  169.     return gs_text_retry(penum->pte_default);
  170.     return_error(gs_error_rangecheck); /* can't happen */
  171. }
  172. private void
  173. pdf_text_release(gs_text_enum_t *pte, client_name_t cname)
  174. {
  175.     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
  176.  
  177.     if (penum->pte_default) {
  178.     gs_text_release(penum->pte_default, cname);
  179.     penum->pte_default = 0;
  180.     }
  181.     gx_default_text_release(pte, cname);
  182. }
  183.  
  184. /* Begin processing text. */
  185. private text_enum_proc_process(pdf_text_process);
  186. private const gs_text_enum_procs_t pdf_text_procs = {
  187.     pdf_text_resync, pdf_text_process,
  188.     pdf_text_is_width_only, pdf_text_current_width,
  189.     pdf_text_set_cache, pdf_text_retry,
  190.     pdf_text_release
  191. };
  192. int
  193. gdev_pdf_text_begin(gx_device * dev, gs_imager_state * pis,
  194.             const gs_text_params_t *text, gs_font * font,
  195.             gx_path * path, const gx_device_color * pdcolor,
  196.             const gx_clip_path * pcpath,
  197.             gs_memory_t * mem, gs_text_enum_t ** ppte)
  198. {
  199.     gx_device_pdf *const pdev = (gx_device_pdf *)dev;
  200.     pdf_text_enum_t *penum;
  201.     gs_fixed_point cpt;
  202.     int code;
  203.  
  204.     /* Track the dominant text rotation. */
  205.     {
  206.     gs_matrix tmat;
  207.     int i;
  208.  
  209.     gs_matrix_multiply(&font->FontMatrix, &ctm_only(pis), &tmat);
  210.     if (is_xxyy(&tmat))
  211.         i = (tmat.xx >= 0 ? 0 : 2);
  212.     else if (is_xyyx(&tmat))
  213.         i = (tmat.xy >= 0 ? 1 : 3);
  214.     else
  215.         i = 4;
  216.     pdf_current_page(pdev)->text_rotation.counts[i] += text->size;
  217.     }
  218.  
  219.     code = pdf_prepare_fill(pdev, pis);
  220.     if (code < 0)
  221.     return code;
  222.  
  223.     if ((text->operation &
  224.      ~(TEXT_FROM_STRING | TEXT_FROM_BYTES |
  225.        TEXT_ADD_TO_ALL_WIDTHS | TEXT_ADD_TO_SPACE_WIDTH |
  226.        TEXT_REPLACE_WIDTHS |
  227.        TEXT_DO_DRAW | TEXT_RETURN_WIDTH)) != 0 ||
  228.     gx_path_current_point(path, &cpt) < 0 ||
  229.     /*
  230.      * It appears that no version of Acrobat Reader handles stroked
  231.      * fonts properly: they all seem to ignore the PaintType.
  232.      * Therefore, we can't handle any font with non-zero PaintType.
  233.      */
  234.     font->PaintType != 0
  235.     )
  236.     return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
  237.                      pcpath, mem, ppte);
  238.  
  239.     /* Set the clipping path and color. */
  240.  
  241.     if (pdf_must_put_clip_path(pdev, pcpath)) {
  242.     int code = pdf_open_page(pdev, PDF_IN_STREAM);
  243.  
  244.     if (code < 0)
  245.         return code;
  246.     pdf_put_clip_path(pdev, pcpath);
  247.     }
  248.     if (pdf_set_drawing_color(pdev, pdcolor, &pdev->fill_color,
  249.                   &psdf_set_fill_color_commands) < 0)
  250.     return gx_default_text_begin(dev, pis, text, font, path, pdcolor,
  251.                      pcpath, mem, ppte);
  252.  
  253.     /* Allocate and initialize the enumerator. */
  254.  
  255.     rc_alloc_struct_1(penum, pdf_text_enum_t, &st_pdf_text_enum, mem,
  256.               return_error(gs_error_VMerror), "gdev_pdf_text_begin");
  257.     penum->rc.free = rc_free_text_enum;
  258.     penum->pte_default = 0; 
  259.     code = gs_text_enum_init((gs_text_enum_t *)penum, &pdf_text_procs,
  260.                  dev, pis, text, font, path, pdcolor, pcpath, mem);
  261.     if (code < 0) {
  262.     gs_free_object(mem, penum, "gdev_pdf_text_begin");
  263.     return code;
  264.     }
  265.  
  266.     if (text->operation & TEXT_RETURN_WIDTH)
  267.     gx_path_current_point(path, &penum->origin);
  268.     *ppte = (gs_text_enum_t *)penum;
  269.  
  270.     return 0;
  271. }
  272.  
  273. /*
  274.  * Create a new pdf_font for a gs_font.  This is a separate procedure only
  275.  * for readability: it is only called from one place in
  276.  * pdf_update_text_state.
  277.  */
  278. private int
  279. create_pdf_font(gx_device_pdf *pdev, gs_font *font, const gs_matrix *pomat,
  280.         pdf_font_t **pppf)
  281. {
  282.     int index = -1;
  283.     pdf_font_t ftemp;
  284.     int BaseEncoding = ENCODING_INDEX_UNKNOWN;
  285.     int same = 0, base_same = 0;
  286.     pdf_font_embed_t embed =
  287.     pdf_font_embed_status(pdev, font, &index, &same);
  288.     bool have_widths = false;
  289.     bool is_standard = false;
  290.     long ffid = 0;
  291.     pdf_font_descriptor_t *pfd;
  292.     gs_font *base_font = font;
  293.     gs_font *below;
  294.     pdf_font_descriptor_t fdesc;
  295.     pdf_font_t *ppf;
  296.     int code;
  297. #define BASE_UID(fnt) (&((const gs_font_base *)(fnt))->UID)
  298.  
  299.     /* Find the "lowest" base font that has the same outlines. */
  300.     while ((below = base_font->base) != base_font &&
  301.        base_font->procs.same_font(base_font, below,
  302.                       FONT_SAME_OUTLINES))
  303.     base_font = below;
  304.  set_base:
  305.     if (base_font == font)
  306.     base_same = same;
  307.     else
  308.     embed = pdf_font_embed_status(pdev, base_font, &index, &base_same);
  309.     if (embed == FONT_EMBED_STANDARD && pdev->std_fonts[index].font != 0) {
  310.     /* Use the standard font as the base font. */
  311.     base_font = pdev->std_fonts[index].font;
  312.     is_standard = true;
  313.     } else if (embed == FONT_EMBED_YES &&
  314.            base_font->FontType != ft_composite &&
  315.            uid_is_valid(BASE_UID(base_font)) &&
  316.            !base_font->is_resource
  317.            ) {
  318.     /*
  319.      * The base font has a UID, but it isn't a resource.  Look for a
  320.      * resource with the same UID, in the hope that that will be
  321.      * longer-lived.
  322.      */
  323.     gs_font *orig = base_font->dir->orig_fonts;
  324.  
  325.     for (; orig; orig = orig->next)
  326.         if (orig != base_font && orig->FontType == base_font->FontType &&
  327.         orig->is_resource &&
  328.         uid_equal(BASE_UID(base_font), BASE_UID(orig))
  329.         ) {
  330.         /* Use this as the base font instead. */
  331.         base_font = orig;
  332.         /*
  333.          * Recompute the embedding status of the base font.  This
  334.          * can't lead to a loop, because base_font->is_resource is
  335.          * now known to be true.
  336.          */
  337.         goto set_base;
  338.         }
  339.     }
  340.      
  341.     /* See if we already have a descriptor for this base font. */
  342.     pfd = (pdf_font_descriptor_t *)
  343.     pdf_find_resource_by_gs_id(pdev, resourceFontDescriptor,
  344.                    base_font->id);
  345.     if (pfd != 0 && pfd->base_font != base_font)
  346.     pfd = 0;
  347.  
  348.     /* Create an appropriate font and descriptor. */
  349.  
  350.     switch (embed) {
  351.     case FONT_EMBED_YES:
  352.     /*
  353.      * HACK: Acrobat Reader 3 has a bug that makes cmap formats 4
  354.      * and 6 not work in embedded TrueType fonts.  Consequently, it
  355.      * can only handle embedded TrueType fonts if all the glyphs
  356.      * referenced by the Encoding have numbers 0-255.  Check for
  357.      * this now.
  358.      */
  359.     if (font->FontType == ft_TrueType &&
  360.         pdev->CompatibilityLevel <= 1.2
  361.         ) {
  362.         int i;
  363.  
  364.         for (i = 0; i <= 0xff; ++i) {
  365.         gs_glyph glyph =
  366.             font->procs.encode_char(font, (gs_char)i,
  367.                         GLYPH_SPACE_INDEX);
  368.  
  369.         if (glyph == gs_no_glyph ||
  370.             (glyph >= gs_min_cid_glyph &&
  371.              glyph <= gs_min_cid_glyph + 0xff)
  372.             )
  373.             continue;
  374.         /* Can't embed, punt. */
  375.         return_error(gs_error_rangecheck);
  376.         }
  377.     }
  378.     code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
  379.     if (code < 0)
  380.         return code;
  381.     if (!pfd)
  382.         ffid = pdf_obj_ref(pdev);
  383.     goto wf;
  384.     case FONT_EMBED_NO:
  385.     /*
  386.      * Per the PDF 1.3 documentation, there are only 3 BaseEncoding
  387.      * values allowed for non-embedded fonts.  Pick one here.
  388.      */
  389.     BaseEncoding =
  390.         ((const gs_font_base *)base_font)->nearest_encoding_index;
  391.     switch (BaseEncoding) {
  392.     default:
  393.         BaseEncoding = ENCODING_INDEX_WINANSI;
  394.     case ENCODING_INDEX_WINANSI:
  395.     case ENCODING_INDEX_MACROMAN:
  396.     case ENCODING_INDEX_MACEXPERT:
  397.         break;
  398.     }
  399.     code = pdf_compute_font_descriptor(pdev, &fdesc, font, NULL);
  400.     if (code < 0)
  401.         return code;
  402.     wf:
  403.     /* The font isn't standard: make sure we write the Widths. */
  404.     same &= ~FONT_SAME_METRICS;
  405.     /* falls through */
  406.     case FONT_EMBED_STANDARD:
  407.     if (~same & (FONT_SAME_METRICS | FONT_SAME_ENCODING)) {
  408.         /*
  409.          * Before allocating the font resource, check that we can
  410.          * get all the widths.
  411.          */
  412.         int i;
  413.  
  414.         memset(&ftemp, 0, sizeof(ftemp));
  415.         for (i = 0; i <= 255; ++i) {
  416.         code = pdf_char_width(&ftemp, i, font, NULL);
  417.         if (code < 0 && code != gs_error_undefined)
  418.             return code;
  419.         }
  420.         have_widths = true;
  421.     }
  422.     if (pfd) {
  423.         code = pdf_alloc_font(pdev, font->id, &ppf, NULL);
  424.         if (code < 0)
  425.         return code;
  426.         if_debug4('_',
  427.               "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (old)\n",
  428.               (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf),
  429.               (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd));
  430.         ppf->FontDescriptor = pfd;
  431.     } else {
  432.         int name_index = index;
  433.  
  434.         fdesc.rid = base_font->id;
  435.         switch (base_font->FontType) {
  436.         case ft_CID_encrypted:
  437.         fdesc.chars_used.size =
  438.             (((const gs_font_cid0 *)base_font)->
  439.              cidata.common.CIDCount + 7) >> 3;
  440.         break;
  441.         case ft_CID_TrueType:
  442.         fdesc.chars_used.size =
  443.             (((const gs_font_cid2 *)base_font)->
  444.              cidata.common.CIDCount + 7) >> 3;
  445.         break;
  446.         default:
  447.         fdesc.chars_used.size = 256/8; /* Encoding size */
  448.         }
  449.         code = pdf_alloc_font(pdev, font->id, &ppf, &fdesc);
  450.         if (code < 0)
  451.         return code;
  452.         pfd = ppf->FontDescriptor;
  453.         if_debug4('_',
  454.               "[_]created pdf_font_t 0x%lx, id %ld, FontDescriptor 0x%lx, id %ld (new)\n",
  455.               (ulong)ppf, pdf_resource_id((pdf_resource_t *)ppf),
  456.               (ulong)pfd, pdf_resource_id((pdf_resource_t *)pfd));
  457.         if (index < 0) {
  458.         int ignore_same;
  459.  
  460.         memcpy(pfd->FontName.chars, base_font->font_name.chars,
  461.                base_font->font_name.size);
  462.         pfd->FontName.size = base_font->font_name.size;
  463.         pfd->FontFile_id = ffid;
  464.         pfd->base_font = base_font;
  465.         pfd->orig_matrix = *pomat;
  466.         /* Don't allow non-standard fonts with standard names. */
  467.         pdf_font_embed_status(pdev, base_font, &name_index,
  468.                       &ignore_same);
  469.         } else {
  470.         /* Use the standard name. */
  471.         const pdf_standard_font_t *ppsf = &pdf_standard_fonts[index];
  472.         const char *fnchars = ppsf->fname;
  473.         uint fnsize = strlen(fnchars);
  474.  
  475.         memcpy(pfd->FontName.chars, fnchars, fnsize);
  476.         pfd->FontName.size = fnsize;
  477.         memset(&pfd->values, 0, sizeof(&pfd->values));
  478.         }
  479.         if (!is_standard) {
  480.         code = pdf_adjust_font_name(pdev, pfd, name_index >= 0);
  481.         if (code < 0)
  482.             return code;
  483.         }
  484.     }
  485.     ppf->FontType = font->FontType;
  486.     ppf->index = index;
  487.     switch (font->FontType) {
  488.     case ft_encrypted:
  489.     case ft_encrypted2:
  490.         ppf->is_MM_instance =
  491.         ((const gs_font_type1 *)font)->data.WeightVector.count > 0;
  492.     default:
  493.         DO_NOTHING;
  494.     }
  495.     ppf->BaseEncoding = BaseEncoding;
  496.     ppf->fname = pfd->FontName;
  497.     ppf->font = font;
  498.     if (~same & FONT_SAME_METRICS) {
  499.         /*
  500.          * Contrary to the PDF 1.3 documentation, FirstChar and
  501.          * LastChar are *not* simply a way to strip off initial and
  502.          * final entries in the Widths array that are equal to
  503.          * MissingWidth.  Acrobat Reader assumes that characters
  504.          * with codes less than FirstChar or greater than LastChar
  505.          * are undefined, without bothering to consult the Encoding.
  506.          * Therefore, the implicit value of MissingWidth is pretty
  507.          * useless, because there must be explicit Width entries for
  508.          * every character in the font that is ever used.
  509.          * Furthermore, if there are several subsets of the same
  510.          * font in a document, it appears to be random as to which
  511.     case ft_CID_TrueType:
  512.          * one Acrobat Reader uses to decide what the FirstChar and
  513.          * LastChar values are.  Therefore, we must write the Widths
  514.          * array for the entire font even for subsets.
  515.          */
  516.         ppf->write_Widths = true;
  517.         pdf_find_char_range(font, &ppf->FirstChar, &ppf->LastChar);
  518.     }
  519.     if (have_widths) {
  520.         /*
  521.          * C's bizarre coercion rules make us use memcpy here
  522.          * rather than direct assignments, even though sizeof()
  523.          * gives the correct value....
  524.          */
  525.         memcpy(ppf->Widths, ftemp.Widths, sizeof(ppf->Widths));
  526.         memcpy(ppf->widths_known, ftemp.widths_known,
  527.            sizeof(ppf->widths_known));
  528.     }
  529.     code = pdf_register_font(pdev, font, ppf);
  530.     }
  531.  
  532.     *pppf = ppf;
  533.     return code;
  534. }
  535.  
  536. /*
  537.  * Compute the cached values in the text state from the text parameters,
  538.  * current_font, and pis->ctm.
  539.  */
  540. private int
  541. pdf_update_text_state(pdf_text_process_state_t *ppts,
  542.               const pdf_text_enum_t *penum, const gs_matrix *pfmat)
  543. {
  544.     gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
  545.     gs_font *font = penum->current_font;
  546.     pdf_font_t *ppf;
  547.     gs_fixed_point cpt;
  548.     gs_matrix orig_matrix, smat, tmat;
  549.     double
  550.     sx = pdev->HWResolution[0] / 72.0,
  551.     sy = pdev->HWResolution[1] / 72.0;
  552.     float chars, words, size;
  553.     int code = gx_path_current_point(penum->path, &cpt);
  554.  
  555.     if (code < 0)
  556.     return code;
  557.  
  558.     /* PDF always uses 1000 units per em for font metrics. */
  559.     switch (font->FontType) {
  560.     case ft_TrueType:
  561.     case ft_CID_TrueType:
  562.     /*
  563.      * ****** HACK ALERT ******
  564.      *
  565.      * The code above that calls pdf_find_char_range does so the first
  566.      * time the font is used.  This causes an incorrect (too small)
  567.      * Widths array to be written if the font is downloaded
  568.      * incrementally.  In practice, this appears only to be a problem
  569.      * for TrueType fonts written by certain Windows drivers
  570.      * (including AdobePS5 for Windows NT).  Fortunately, it is easy
  571.      * to determine whether the font is an incremental one: this is
  572.      * the case iff the font doesn't have glyf and loca entries.
  573.      * In this case, we punt and treat the font as bitmaps.
  574.      */
  575.     if (((const gs_font_type42 *)font)->data.glyf == 0)
  576.         return_error(gs_error_rangecheck); /* incremental */
  577.     /* The TrueType FontMatrix is 1 unit per em, which is what we want. */
  578.     gs_make_identity(&orig_matrix);
  579.     break;
  580.     case ft_encrypted:
  581.     case ft_encrypted2:
  582.     case ft_CID_encrypted:
  583.     gs_make_scaling(0.001, 0.001, &orig_matrix);
  584.     break;
  585.     default:
  586.     return_error(gs_error_rangecheck);
  587.     }
  588.     DISCARD(pdf_find_orig_font(pdev, font, &orig_matrix));
  589.  
  590.     /* Compute the scaling matrix and combined matrix. */
  591.  
  592.     gs_matrix_invert(&orig_matrix, &smat);
  593.     gs_matrix_multiply(&smat, pfmat, &smat);
  594.     tmat = ctm_only(penum->pis);
  595.     tmat.tx = tmat.ty = 0;
  596.     gs_matrix_multiply(&smat, &tmat, &tmat);
  597.  
  598.     /* Try to find a reasonable size value.  This isn't necessary, */
  599.     /* but it's worth a little effort. */
  600.  
  601.     size = fabs(tmat.yy) / sy;
  602.     if (size < 0.01)
  603.     size = fabs(tmat.xx) / sx;
  604.     if (size < 0.01)
  605.     size = 1;
  606.  
  607.     /* Check for spacing parameters we can handle, and transform them. */
  608.  
  609.     if (penum->text.operation & TEXT_ADD_TO_ALL_WIDTHS) {
  610.     gs_point pt;
  611.  
  612.     gs_distance_transform_inverse(penum->text.delta_all.x,
  613.                       penum->text.delta_all.y,
  614.                       &smat, &pt);
  615.     if (pt.y != 0)
  616.         return_error(gs_error_rangecheck);
  617.     chars = pt.x * size;
  618.     } else
  619.     chars = 0.0;
  620.  
  621.     if (penum->text.operation & TEXT_ADD_TO_SPACE_WIDTH) {
  622.     gs_point pt;
  623.  
  624.     gs_distance_transform_inverse(penum->text.delta_space.x,
  625.                       penum->text.delta_space.y,
  626.                       &smat, &pt);
  627.     if (pt.y != 0 || penum->text.space.s_char != 32)
  628.         return_error(gs_error_rangecheck);
  629.     words = pt.x * size;
  630.     } else
  631.     words = 0.0;
  632.  
  633.     /* Find or create the font resource. */
  634.  
  635.     ppf = (pdf_font_t *)
  636.     pdf_find_resource_by_gs_id(pdev, resourceFont, font->id);
  637.     /* Check for the possibility that the base font has been freed. */
  638.     if (ppf && ppf->FontDescriptor->written)
  639.     ppf = 0;
  640.     if (ppf == 0 || ppf->font == 0) {
  641.     code = create_pdf_font(pdev, font, &orig_matrix, &ppf);
  642.     if (code < 0)
  643.         return code;
  644.     }
  645.  
  646.     /* Store the updated values. */
  647.  
  648.     tmat.xx /= size;
  649.     tmat.xy /= size;
  650.     tmat.yx /= size;
  651.     tmat.yy /= size;
  652.     tmat.tx += fixed2float(cpt.x);
  653.     tmat.ty += fixed2float(cpt.y);
  654.  
  655.     ppts->chars = chars;
  656.     ppts->words = words;
  657.     ppts->size = size;
  658.     ppts->text_matrix = tmat;
  659.     ppts->pdfont = ppf;
  660.  
  661.     return 0;
  662. }
  663.  
  664. /* Check whether a glyph exists in a (pseudo-)encoding. */
  665. private bool
  666. encoding_has_glyph(gs_font_base *bfont, gs_glyph font_glyph,
  667.            gs_encoding_index_t index)
  668. {
  669.     int ch;
  670.     gs_glyph glyph;
  671.  
  672.     for (ch = 0;
  673.      (glyph = bfont->procs.callbacks.known_encode((gs_char)ch, index)) !=
  674.          gs_no_glyph;
  675.      ++ch)
  676.     if (glyph == font_glyph)
  677.         return true;
  678.     return false;
  679. }
  680.  
  681. /*
  682.  * For a given character, check whether the encoding of bfont (the current
  683.  * font) is compatible with that of the underlying unscaled, possibly
  684.  * standard, base font, and if not, whether we can re-encode the character
  685.  * using the base font's encoding.  Return the (possibly re-encoded)
  686.  * character if successful.
  687.  */
  688. inline private void
  689. record_used(pdf_font_descriptor_t *pfd, int c)
  690. {
  691.     pfd->chars_used.data[c >> 3] |= 1 << (c & 7);
  692. }
  693. private int
  694. pdf_encode_char(gx_device_pdf *pdev, int chr, gs_font_base *bfont,
  695.         pdf_font_t *ppf)
  696. {
  697.     pdf_font_descriptor_t *const pfd = ppf->FontDescriptor;
  698.     /*
  699.      * bfont is the current font in which the text is being shown.
  700.      * ei is its encoding_index.
  701.      */
  702.     gs_encoding_index_t ei = bfont->encoding_index;
  703.     /*
  704.      * base_font is the font that underlies this PDF font (i.e., this PDF
  705.      * font is base_font plus some possible Encoding and Widths differences,
  706.      * and possibly a different FontMatrix).  base_font is 0 iff this PDF
  707.      * font is one of the standard 14 (i.e., ppf->index !=
  708.      * ENCODING_INDEX_UNKNOWN).  bei is the index of the BaseEncoding
  709.      * (explicit or, for the standard fonts, implicit) that will be written
  710.      * in the PDF file: it is not necessarily the same as
  711.      * base_font->encoding_index, or even base_font->nearest_encoding_index.
  712.      */
  713.     gs_font *base_font = pfd->base_font;
  714.     bool have_font = base_font != 0 && base_font->FontType != ft_composite;
  715.     bool is_standard = ppf->index != ENCODING_INDEX_UNKNOWN;
  716.     gs_encoding_index_t bei =
  717.     (ppf->BaseEncoding != ENCODING_INDEX_UNKNOWN ? ppf->BaseEncoding :
  718.      is_standard ? pdf_standard_fonts[ppf->index].base_encoding :
  719.      ENCODING_INDEX_UNKNOWN);
  720.     pdf_encoding_element_t *pdiff = ppf->Differences;
  721.     /*
  722.      * If set, font_glyph is the glyph currently associated with chr in
  723.      * base_font + bei + diffs; glyph is the glyph corresponding to chr in
  724.      * bfont.
  725.      */
  726.     gs_glyph font_glyph, glyph;
  727. #define IS_USED(c)\
  728.   (((pfd)->chars_used.data[(c) >> 3] & (1 << ((c) & 7))) != 0)
  729.  
  730.     if (ei == bei && ei != ENCODING_INDEX_UNKNOWN && pdiff == 0) {
  731.     /*
  732.      * Just note that the character has been used with its original
  733.      * encoding.
  734.      */
  735.     record_used(pfd, chr);
  736.     return chr;
  737.     }
  738.     if (!is_standard && !have_font)
  739.     return_error(gs_error_undefined); /* can't encode */
  740.  
  741. #define ENCODE_NO_DIFF(ch)\
  742.    (bei != ENCODING_INDEX_UNKNOWN ?\
  743.     bfont->procs.callbacks.known_encode((gs_char)(ch), bei) :\
  744.     /* have_font */ bfont->procs.encode_char(base_font, chr, GLYPH_SPACE_NAME))
  745. #define HAS_DIFF(ch) (pdiff != 0 && pdiff[ch].str.data != 0)
  746. #define ENCODE_DIFF(ch) (pdiff[ch].glyph)
  747. #define ENCODE(ch)\
  748.   (HAS_DIFF(ch) ? ENCODE_DIFF(ch) : ENCODE_NO_DIFF(ch))
  749.  
  750.     font_glyph = ENCODE(chr);
  751.     glyph =
  752.     (ei == ENCODING_INDEX_UNKNOWN ?
  753.      bfont->procs.encode_char((gs_font *)bfont, chr, GLYPH_SPACE_NAME) :
  754.      bfont->procs.callbacks.known_encode(chr, ei));
  755.     if (glyph == font_glyph) {
  756.     record_used(pfd, chr);
  757.     return chr;
  758.     }
  759.  
  760.     if (ppf->index == ENCODING_INDEX_UNKNOWN && pfd->FontFile_id == 0 &&
  761.     pdev->CompatibilityLevel <= 1.2
  762.     ) {
  763.     /*
  764.      * Work around the bug in Acrobat Reader 3's Print function
  765.      * that makes re-encoded characters in substituted fonts
  766.      * print as blank.
  767.      */
  768.     return_error(gs_error_undefined);
  769.     }
  770.  
  771.     /*
  772.      * TrueType fonts don't allow Differences in the encoding, but we might
  773.      * be able to re-encode the character if it appears elsewhere in the
  774.      * encoding.
  775.      */
  776.     if (bfont->FontType == ft_TrueType) {
  777.     if (pdev->ReEncodeCharacters) {
  778.         int c;
  779.  
  780.         for (c = 0; c < 256; ++c)
  781.         if (ENCODE_NO_DIFF(c) == glyph) {
  782.             record_used(pfd, c);
  783.             return c;
  784.         }
  785.     }
  786.     return_error(gs_error_undefined);
  787.     }
  788.  
  789.     /*
  790.      * If the font isn't going to be embedded, check whether this glyph is
  791.      * available in the base font's glyph set at all.
  792.      */
  793.     if (pfd->FontFile_id == 0) {
  794.     switch (bei) {
  795.     case ENCODING_INDEX_STANDARD:
  796.     case ENCODING_INDEX_ISOLATIN1:
  797.     case ENCODING_INDEX_WINANSI:
  798.     case ENCODING_INDEX_MACROMAN:
  799.         /* Check the full Adobe glyph set(s). */
  800.         if (!encoding_has_glyph(bfont, glyph, ENCODING_INDEX_ALOGLYPH) &&
  801.         (pdev->CompatibilityLevel < 1.3 ||
  802.          !encoding_has_glyph(bfont, glyph, ENCODING_INDEX_ALXGLYPH))
  803.         )
  804.         return_error(gs_error_undefined);
  805.     default:
  806.         break;
  807.     }
  808.     }
  809.  
  810.     if (pdev->ReAssignCharacters) {
  811.     /*
  812.      * If this is the first time we've seen this character,
  813.      * assign the glyph to its position in the encoding.
  814.      */
  815.     if (!HAS_DIFF(chr) && !IS_USED(chr)) {
  816.         int code =
  817.         pdf_add_encoding_difference(pdev, ppf, chr, bfont, glyph);
  818.  
  819.         if (code >= 0) {
  820.         /*
  821.          * As noted in the comments at the beginning of this file,
  822.          * we don't have any way to record, for the purpose of
  823.          * subsetting, the fact that a particular unencoded glyph
  824.          * was used.  If this glyph doesn't appear anywhere else in
  825.          * the base encoding, fall back to writing the entire font.
  826.          */
  827.         int c;
  828.  
  829.         for (c = 0; c < 256; ++c)
  830.             if (ENCODE_NO_DIFF(c) == glyph)
  831.             break;
  832.         if (c < 256)    /* found */
  833.             record_used(pfd, c);
  834.         else        /* not found */
  835.             pfd->subset_ok = false;
  836.         return chr;
  837.         }
  838.     }
  839.     }
  840.  
  841.     if (pdev->ReEncodeCharacters) {
  842.     /*
  843.      * Look for the character at some other position in the
  844.      * encoding.
  845.      */
  846.     int c, code;
  847.  
  848.     for (c = 0; c < 256; ++c) {
  849.         if (HAS_DIFF(c)) {
  850.         if (ENCODE_DIFF(c) == glyph)
  851.             return c;
  852.         } else if (ENCODE_NO_DIFF(c) == glyph) {
  853.         record_used(pfd, c);
  854.         return c;
  855.         }
  856.     }
  857.     /*
  858.      * The character isn't encoded anywhere.  Look for a
  859.      * never-referenced .notdef position where we can put it.
  860.      */
  861.     for (c = 0; c < 256; ++c) {
  862.         gs_const_string gnstr;
  863.  
  864.         if (HAS_DIFF(c) || IS_USED(c))
  865.         continue; /* slot already referenced */
  866.         font_glyph = ENCODE_NO_DIFF(c);
  867.         if (font_glyph == gs_no_glyph)
  868.         break;
  869.         gnstr.data = (const byte *)
  870.         bfont->procs.callbacks.glyph_name(font_glyph,
  871.                           &gnstr.size);
  872.         if (gnstr.size == 7 &&
  873.         !memcmp(gnstr.data, ".notdef", 7)
  874.         )
  875.         break;
  876.     }
  877.     if (c == 256)    /* no .notdef positions left */
  878.         return_error(gs_error_undefined);
  879.     code = pdf_add_encoding_difference(pdev, ppf, c, bfont, glyph);
  880.     if (code < 0)
  881.         return code;
  882.     /* See under ReAssignCharacters above regarding the following: */
  883.     pfd->subset_ok = false;
  884.     return c;
  885.     }
  886.  
  887.     return_error(gs_error_undefined);
  888.  
  889. #undef IS_USED
  890. #undef ENCODE_NO_DIFF
  891. #undef HAS_DIFF
  892. #undef ENCODE_DIFF
  893. #undef ENCODE
  894. }
  895.  
  896. /*
  897.  * Write out commands to make the output state match the processing state.
  898.  */
  899. private int
  900. pdf_write_text_process_state(gx_device_pdf *pdev,
  901.                  const pdf_text_process_state_t *ppts,
  902.                  const gs_const_string *pstr)
  903. {
  904.     int code;
  905.     stream *s;
  906.  
  907.     pdf_set_font_and_size(pdev, ppts->pdfont, ppts->size);
  908.     code = pdf_set_text_matrix(pdev, &ppts->text_matrix);
  909.     if (code < 0)
  910.     return code;
  911.  
  912.     if (pdev->text.character_spacing != ppts->chars &&
  913.     pstr->size + pdev->text.buffer_count > 1
  914.     ) {
  915.     code = pdf_open_page(pdev, PDF_IN_TEXT);
  916.     if (code < 0)
  917.         return code;
  918.     s = pdev->strm;
  919.     pprintg1(s, "%g Tc\n", ppts->chars);
  920.     pdev->text.character_spacing = ppts->chars;
  921.     }
  922.  
  923.     if (pdev->text.word_spacing != ppts->words &&
  924.     (memchr(pstr->data, 32, pstr->size) ||
  925.      memchr(pdev->text.buffer, 32, pdev->text.buffer_count))
  926.     ) {
  927.     code = pdf_open_page(pdev, PDF_IN_TEXT);
  928.     if (code < 0)
  929.         return code;
  930.     s = pdev->strm;
  931.     pprintg1(s, "%g Tw\n", ppts->words);
  932.     pdev->text.word_spacing = ppts->words;
  933.     }
  934.  
  935.     return 0;
  936. }
  937.  
  938. /*
  939.  * Continue processing text.  Per the check in pdf_text_begin, we know the
  940.  * operation is TEXT_FROM_STRING/BYTES, TEXT_DO_DRAW, and possibly
  941.  * TEXT_ADD_TO_ALL_WIDTHS, TEXT_ADD_TO_SPACE_WIDTH, TEXT_REPLACE_WIDTHS,
  942.  * and/or TEXT_RETURN_WIDTH.
  943.  */
  944. private int
  945. pdf_text_process(gs_text_enum_t *pte)
  946. {
  947.     pdf_text_enum_t *const penum = (pdf_text_enum_t *)pte;
  948.     gx_device_pdf *const pdev = (gx_device_pdf *)penum->dev;
  949.     gs_text_enum_t *pte_default = penum->pte_default;
  950.     gs_font *font;
  951.     gs_matrix fmat;
  952.     const gs_text_params_t *text = &pte->text;
  953.     gs_text_params_t alt_text;
  954.     pdf_text_process_state_t text_state;
  955.     gs_const_string str;
  956.     int i;
  957.     byte strbuf[200];        /* arbitrary */
  958.     int code;
  959.  
  960.  top:
  961.     if (pte_default) {
  962.     /* Continue processing using the default algorithms. */
  963.     code = gs_text_process(pte_default);
  964.     gs_text_enum_copy_dynamic(pte, pte_default, true);
  965.     if (code)
  966.         return code;
  967.     gs_text_release(pte_default, "pdf_text_process");
  968.     penum->pte_default = pte_default = 0;
  969.     /****** FOR NOW ******/
  970.     return 0;
  971.     }
  972.     str.data = text->data.bytes;
  973.     str.size = text->size;
  974.     font = penum->current_font;
  975.     fmat = font->FontMatrix;
  976.  fnt:
  977.     switch (font->FontType) {
  978.     case ft_TrueType:
  979.     case ft_encrypted:
  980.     case ft_encrypted2:
  981.     break;
  982.     case ft_composite: {
  983.     gs_font_type0 *const font0 = (gs_font_type0 *)font;
  984.     /*
  985.      * Support just one special format, which is used by some versions
  986.      * of the Adobe PS4 driver even for single-byte text.
  987.      */
  988.     switch (font0->data.FMapType) {
  989.     case fmap_8_8:
  990.         if (str.size > sizeof(strbuf) * 2)
  991.         goto dflt;
  992.         for (i = 0; i < str.size; i += 2) {
  993.         if (str.data[i] != 0)
  994.             goto dflt;
  995.         strbuf[i >> 1] = str.data[i + 1];
  996.         }
  997.         str.data = strbuf;
  998.         str.size >>= 1;
  999.         font = penum->current_font = font0->data.FDepVector[0];
  1000.         /*
  1001.          * The FontMatrix of descendant base fonts is not scaled by
  1002.          * scalefont/makefont.
  1003.          */
  1004.         if (font->FontType != ft_composite)
  1005.         gs_matrix_multiply(&fmat, &font->FontMatrix, &fmat);
  1006.         goto fnt;
  1007.     default:
  1008.         goto dflt;
  1009.     }
  1010.     break;
  1011.     }
  1012.     default:
  1013.     goto dflt;
  1014.     }
  1015.  
  1016.     code = pdf_update_text_state(&text_state, penum, &fmat);
  1017.     if (code < 0)
  1018.     goto dflt;
  1019.  
  1020.     /* Check that all characters can be encoded. */
  1021.  
  1022.     for (i = 0; i < str.size; ++i) {
  1023.     int chr = str.data[i];
  1024.     int code = pdf_encode_char(pdev, chr, (gs_font_base *)font,
  1025.                    text_state.pdfont);
  1026.  
  1027.     if (code < 0)
  1028.         goto dflt;
  1029.     if (code != chr) {
  1030.         /*
  1031.          * It really simplifies things if we can buffer
  1032.          * the entire string locally in one piece....
  1033.          */
  1034.         if (str.data != strbuf) {
  1035.         if (str.size > sizeof(strbuf))
  1036.             goto dflt;
  1037.         memcpy(strbuf, str.data, str.size);
  1038.         str.data = strbuf;
  1039.         }
  1040.         strbuf[i] = (byte)code;
  1041.     }
  1042.     }
  1043.  
  1044.     /* Bring the text-related parameters in the output up to date. */
  1045.  
  1046.     /*
  1047.      * The following check is necessary, because pdf_set_text_matrix
  1048.      * assumes that a string-showing operator will follow.
  1049.      */
  1050.     if (pte->index < str.size) {
  1051.     code = pdf_write_text_process_state(pdev, &text_state, &str);
  1052.     if (code < 0)
  1053.         goto dflt;
  1054.     }
  1055.  
  1056.     if (text->operation & TEXT_REPLACE_WIDTHS) {
  1057.     gs_point w;
  1058.     gs_matrix tmat;
  1059.  
  1060.     w.x = w.y = 0;
  1061.     tmat = text_state.text_matrix;
  1062.     for (; pte->index < str.size; pte->index++, pte->xy_index++) {
  1063.         gs_point d, dpt;
  1064.  
  1065.         code = pdf_append_chars(pdev, str.data + pte->index, 1);
  1066.         if (code < 0)
  1067.         return code;
  1068.         gs_text_replaced_width(&pte->text, pte->xy_index, &d);
  1069.         w.x += d.x, w.y += d.y;
  1070.         gs_distance_transform(d.x, d.y, &ctm_only(pte->pis), &dpt);
  1071.         tmat.tx += dpt.x;
  1072.         tmat.ty += dpt.y;
  1073.         if (pte->index + 1 < str.size) {
  1074.         code = pdf_set_text_matrix(pdev, &tmat);
  1075.         if (code < 0)
  1076.             return code;
  1077.         }
  1078.     }
  1079.     pte->returned.total_width = w;
  1080.     return
  1081.         (text->operation & TEXT_RETURN_WIDTH ?
  1082.          gx_path_add_point(pte->path, float2fixed(tmat.tx),
  1083.                    float2fixed(tmat.ty)) :
  1084.          0);
  1085.     }
  1086.     code = pdf_append_chars(pdev, str.data + pte->index,
  1087.                 str.size - pte->index);
  1088.     pte->index = 0;
  1089.     if (code < 0)
  1090.     goto dflt;
  1091.     /*
  1092.      * If we don't need the widths, return now.  If the widths are
  1093.      * available directly from the font, compute and return the total
  1094.      * width now.  Otherwise, call the default implementation.
  1095.      */
  1096.     if (!(text->operation & TEXT_RETURN_WIDTH))
  1097.     return 0;
  1098.     {
  1099.     int i, w;
  1100.     double scale = (font->FontType == ft_TrueType ? 0.001 : 1.0);
  1101.     gs_point dpt;
  1102.     int num_spaces = 0;
  1103.  
  1104.     for (i = pte->index, w = 0; i < str.size; ++i) {
  1105.         int cw;
  1106.         int code =
  1107.         pdf_char_width(text_state.pdfont, str.data[i], font, &cw);
  1108.  
  1109.         if (code < 0)
  1110.         goto dflt_w;
  1111.         w += cw;
  1112.         if (str.data[i] == ' ')
  1113.         ++num_spaces;
  1114.     }
  1115.     gs_distance_transform(w * scale, 0.0, &font->FontMatrix, &dpt);
  1116.     if (text->operation & TEXT_ADD_TO_ALL_WIDTHS) {
  1117.         int num_chars = str.size - pte->index;
  1118.  
  1119.         dpt.x += penum->text.delta_all.x * num_chars;
  1120.         dpt.y += penum->text.delta_all.y * num_chars;
  1121.     }
  1122.     if (text->operation & TEXT_ADD_TO_SPACE_WIDTH) {
  1123.         dpt.x += penum->text.delta_space.x * num_spaces;
  1124.         dpt.y += penum->text.delta_space.y * num_spaces;
  1125.     }
  1126.     pte->returned.total_width = dpt;
  1127.     gs_distance_transform(dpt.x, dpt.y, &ctm_only(pte->pis), &dpt);
  1128.     return gx_path_add_point(pte->path,
  1129.                  penum->origin.x + float2fixed(dpt.x),
  1130.                  penum->origin.y + float2fixed(dpt.y));
  1131.     }
  1132.  dflt_w:
  1133.     alt_text = *text;
  1134.     alt_text.operation ^= TEXT_DO_DRAW | TEXT_DO_CHARWIDTH;
  1135.     text = &alt_text;
  1136.  dflt:
  1137.     code = gx_default_text_begin(pte->dev, pte->pis, text, pte->current_font,
  1138.                  pte->path, pte->pdcolor, pte->pcpath,
  1139.                  pte->memory, &penum->pte_default);
  1140.     if (code < 0)
  1141.     return code;
  1142.     pte_default = penum->pte_default;
  1143.     gs_text_enum_copy_dynamic(pte_default, pte, false);
  1144.     goto top;
  1145. }
  1146.  
  1147. /* ---------------- Text and font utilities ---------------- */
  1148.  
  1149. /* Forward declarations */
  1150. private int assign_char_code(P1(gx_device_pdf * pdev));
  1151.  
  1152. /*
  1153.  * Set the current font and size, writing a Tf command if needed.
  1154.  */
  1155. private int
  1156. pdf_set_font_and_size(gx_device_pdf * pdev, pdf_font_t * font, floatp size)
  1157. {
  1158.     if (font != pdev->text.font || size != pdev->text.size) {
  1159.     int code = pdf_open_page(pdev, PDF_IN_TEXT);
  1160.     stream *s = pdev->strm;
  1161.  
  1162.     if (code < 0)
  1163.         return code;
  1164.     pprints1(s, "/%s ", font->frname);
  1165.     pprintg1(s, "%g Tf\n", size);
  1166.     pdev->text.font = font;
  1167.     pdev->text.size = size;
  1168.     }
  1169.     font->used_on_page = true;
  1170.     return 0;
  1171. }
  1172.  
  1173. /*
  1174.  * Set the text matrix for writing text.
  1175.  * The translation component of the matrix is the text origin.
  1176.  * If the non-translation components of the matrix differ from the
  1177.  * current ones, write a Tm command; if there is only a Y translation
  1178.  * and it matches the leading, set use_leading so the next text string
  1179.  * will be written with ' rather than Tj; otherwise, write either a TL
  1180.  * command or a Tj command using space pseudo-characters.
  1181.  */
  1182. private int
  1183. set_text_distance(gs_point *pdist, const gs_point *ppt, const gs_matrix *pmat)
  1184. {
  1185.     double rounded;
  1186.  
  1187.     gs_distance_transform_inverse(pmat->tx - ppt->x, pmat->ty - ppt->y,
  1188.                   pmat, pdist);
  1189.     /* If the distance is very close to integers, round it. */
  1190.     if (fabs(pdist->x - (rounded = floor(pdist->x + 0.5))) < 0.0005)
  1191.     pdist->x = rounded;
  1192.     if (fabs(pdist->y - (rounded = floor(pdist->y + 0.5))) < 0.0005)
  1193.     pdist->y = rounded;
  1194.     return 0;
  1195. }
  1196. private int
  1197. pdf_set_text_matrix(gx_device_pdf * pdev, const gs_matrix * pmat)
  1198. {
  1199.     stream *s = pdev->strm;
  1200.     double sx = 72.0 / pdev->HWResolution[0],
  1201.     sy = 72.0 / pdev->HWResolution[1];
  1202.     int code;
  1203.  
  1204.     if (pmat->xx == pdev->text.matrix.xx &&
  1205.     pmat->xy == pdev->text.matrix.xy &&
  1206.     pmat->yx == pdev->text.matrix.yx &&
  1207.     pmat->yy == pdev->text.matrix.yy &&
  1208.     /*
  1209.      * If we aren't already in text context, BT will reset
  1210.      * the text matrix.
  1211.      */
  1212.     (pdev->context == PDF_IN_TEXT || pdev->context == PDF_IN_STRING)
  1213.     ) {
  1214.     /* Use leading, Td or a pseudo-character. */
  1215.     gs_point dist;
  1216.  
  1217.     set_text_distance(&dist, &pdev->text.current, pmat);
  1218.     if (dist.y == 0 && dist.x >= X_SPACE_MIN &&
  1219.         dist.x <= X_SPACE_MAX &&
  1220.         pdev->text.font != 0 &&
  1221.         PDF_FONT_IS_SYNTHESIZED(pdev->text.font)
  1222.         ) {            /* Use a pseudo-character. */
  1223.         int dx = (int)dist.x;
  1224.         int dx_i = dx - X_SPACE_MIN;
  1225.         byte space_char = pdev->text.font->spaces[dx_i];
  1226.  
  1227.         if (space_char == 0) {
  1228.         if (pdev->text.font != pdev->open_font)
  1229.             goto not_spaces;
  1230.         code = assign_char_code(pdev);
  1231.         if (code <= 0)
  1232.             goto not_spaces;
  1233.         space_char = pdev->open_font->spaces[dx_i] = (byte)code;
  1234.         if (pdev->space_char_ids[dx_i] == 0) {
  1235.             /* Create the space char_proc now. */
  1236.             char spstr[3 + 14 + 1];
  1237.             stream *s;
  1238.  
  1239.             sprintf(spstr, "%d 0 0 0 0 0 d1\n", dx);
  1240.             pdev->space_char_ids[dx_i] = pdf_begin_separate(pdev);
  1241.             s = pdev->strm;
  1242.             pprintd1(s, "<</Length %d>>\nstream\n", strlen(spstr));
  1243.             pprints1(s, "%sendstream\n", spstr);
  1244.             pdf_end_separate(pdev);
  1245.         }
  1246.         }
  1247.         pdf_append_chars(pdev, &space_char, 1);
  1248.         pdev->text.current.x += dx * pmat->xx;
  1249.         pdev->text.use_leading = false;
  1250.         return 0;
  1251.     }
  1252.       not_spaces:
  1253.     code = pdf_open_page(pdev, PDF_IN_TEXT);
  1254.     if (code < 0)
  1255.         return code;
  1256.     if (dist.x == 0 && dist.y < 0) {
  1257.         /* Use TL, if needed, + '. */
  1258.         float dist_y = (float)-dist.y;
  1259.  
  1260.         if (fabs(pdev->text.leading - dist_y) > 0.0005) {
  1261.         pprintg1(s, "%g TL\n", dist_y);
  1262.         pdev->text.leading = dist_y;
  1263.         }
  1264.         pdev->text.use_leading = true;
  1265.     } else {
  1266.         /* Use Td. */
  1267.         set_text_distance(&dist, &pdev->text.line_start, pmat);
  1268.         pprintg2(s, "%g %g Td\n", dist.x, dist.y);
  1269.         pdev->text.use_leading = false;
  1270.     }
  1271.     } else {            /* Use Tm. */
  1272.     code = pdf_open_page(pdev, PDF_IN_TEXT);
  1273.     if (code < 0)
  1274.         return code;
  1275.     /*
  1276.      * See stream_to_text in gdevpdf.c for why we need the following
  1277.      * matrix adjustments.
  1278.      */
  1279.     pprintg6(pdev->strm, "%g %g %g %g %g %g Tm\n",
  1280.          pmat->xx * sx, pmat->xy * sy,
  1281.          pmat->yx * sx, pmat->yy * sy,
  1282.          pmat->tx * sx, pmat->ty * sy);
  1283.     pdev->text.matrix = *pmat;
  1284.     pdev->text.use_leading = false;
  1285.     }
  1286.     pdev->text.line_start.x = pmat->tx;
  1287.     pdev->text.line_start.y = pmat->ty;
  1288.     pdev->text.current.x = pmat->tx;
  1289.     pdev->text.current.y = pmat->ty;
  1290.     return 0;
  1291. }
  1292.  
  1293. /* Append characters to a string being accumulated. */
  1294. private int
  1295. pdf_append_chars(gx_device_pdf * pdev, const byte * str, uint size)
  1296. {
  1297.     const byte *p = str;
  1298.     uint left = size;
  1299.  
  1300.     while (left)
  1301.     if (pdev->text.buffer_count == max_text_buffer) {
  1302.         int code = pdf_open_page(pdev, PDF_IN_TEXT);
  1303.  
  1304.         if (code < 0)
  1305.         return code;
  1306.     } else {
  1307.         int code = pdf_open_page(pdev, PDF_IN_STRING);
  1308.         uint copy;
  1309.  
  1310.         if (code < 0)
  1311.         return code;
  1312.         copy = min(max_text_buffer - pdev->text.buffer_count, left);
  1313.         memcpy(pdev->text.buffer + pdev->text.buffer_count, p, copy);
  1314.         pdev->text.buffer_count += copy;
  1315.         p += copy;
  1316.         left -= copy;
  1317.     }
  1318.     return 0;
  1319. }
  1320.  
  1321. /* ---------------- Synthesized fonts ---------------- */
  1322.  
  1323. /* Assign a code for a char_proc. */
  1324. private int
  1325. assign_char_code(gx_device_pdf * pdev)
  1326. {
  1327.     pdf_font_t *font = pdev->open_font;
  1328.  
  1329.     if (pdev->embedded_encoding_id == 0) {
  1330.     long id = pdf_begin_separate(pdev);
  1331.     stream *s = pdev->strm;
  1332.     int i;
  1333.  
  1334.     /*
  1335.      * Even though the PDF reference documentation says that a
  1336.      * BaseEncoding key is required unless the encoding is
  1337.      * "based on the base font's encoding" (and there is no base
  1338.      * font in this case), Acrobat 2.1 gives an error if the
  1339.      * BaseEncoding key is present.
  1340.      */
  1341.     pputs(s, "<</Type/Encoding/Differences[0");
  1342.     for (i = 0; i < 256; ++i) {
  1343.         if (!(i & 15))
  1344.         pputs(s, "\n");
  1345.         pprintd1(s, "/a%d", i);
  1346.     }
  1347.     pputs(s, "\n] >>\n");
  1348.     pdf_end_separate(pdev);
  1349.     pdev->embedded_encoding_id = id;
  1350.     }
  1351.     if (font == 0 || font->num_chars == 256 || !pdev->use_open_font) {
  1352.     /* Start a new synthesized font. */
  1353.     int code = pdf_alloc_font(pdev, gs_no_id, &font, NULL);
  1354.     char *pc;
  1355.  
  1356.     if (code < 0)
  1357.         return code;
  1358.     if (pdev->open_font == 0)
  1359.         memset(font->frname, 0, sizeof(font->frname));
  1360.     else
  1361.         strcpy(font->frname, pdev->open_font->frname);
  1362.     for (pc = font->frname; *pc == 'Z'; ++pc)
  1363.         *pc = '@';
  1364.     if ((*pc)++ == 0)
  1365.         *pc = 'A', pc[1] = 0;
  1366.     pdev->open_font = font;
  1367.     pdev->use_open_font = true;
  1368.     }
  1369.     return font->num_chars++;
  1370. }
  1371.  
  1372. /* Begin a CharProc for a synthesized (bitmap) font. */
  1373. int
  1374. pdf_begin_char_proc(gx_device_pdf * pdev, int w, int h, int x_width,
  1375.   int y_offset, gs_id id, pdf_char_proc_t ** ppcp, pdf_stream_position_t * ppos)
  1376. {
  1377.     pdf_resource_t *pres;
  1378.     pdf_char_proc_t *pcp;
  1379.     int char_code = assign_char_code(pdev);
  1380.     pdf_font_t *font = pdev->open_font;
  1381.     int code;
  1382.  
  1383.     if (char_code < 0)
  1384.     return char_code;
  1385.     code = pdf_begin_resource(pdev, resourceCharProc, id, &pres);
  1386.     if (code < 0)
  1387.     return code;
  1388.     pcp = (pdf_char_proc_t *) pres;
  1389.     pcp->font = font;
  1390.     pcp->char_next = font->char_procs;
  1391.     font->char_procs = pcp;
  1392.     pcp->char_code = char_code;
  1393.     pcp->width = w;
  1394.     pcp->height = h;
  1395.     pcp->x_width = x_width;
  1396.     pcp->y_offset = y_offset;
  1397.     font->max_y_offset = max(font->max_y_offset, h + (h >> 2));
  1398.     *ppcp = pcp;
  1399.     {
  1400.     stream *s = pdev->strm;
  1401.  
  1402.     /*
  1403.      * The resource file is positionable, so rather than use an
  1404.      * object reference for the length, we'll go back and fill it in
  1405.      * at the end of the definition.  Take 10K as the longest
  1406.      * definition we can handle.
  1407.      */
  1408.     pputs(s, "<</Length     >>\nstream\n");
  1409.     ppos->start_pos = stell(s);
  1410.     }
  1411.     return 0;
  1412. }
  1413.  
  1414. /* End a CharProc. */
  1415. int
  1416. pdf_end_char_proc(gx_device_pdf * pdev, pdf_stream_position_t * ppos)
  1417. {
  1418.     stream *s = pdev->strm;
  1419.     long start_pos = ppos->start_pos;
  1420.     long end_pos = stell(s);
  1421.     long length = end_pos - start_pos;
  1422.  
  1423.     if (length > 9999)
  1424.     return_error(gs_error_limitcheck);
  1425.     sseek(s, start_pos - 14);
  1426.     pprintd1(s, "%d", length);
  1427.     sseek(s, end_pos);
  1428.     pputs(s, "endstream\n");
  1429.     pdf_end_separate(pdev);
  1430.     return 0;
  1431. }
  1432.  
  1433. /* Put out a reference to an image as a character in a synthesized font. */
  1434. int
  1435. pdf_do_char_image(gx_device_pdf * pdev, const pdf_char_proc_t * pcp,
  1436.           const gs_matrix * pimat)
  1437. {
  1438.     pdf_set_font_and_size(pdev, pcp->font, 1.0);
  1439.     {
  1440.     gs_matrix tmat;
  1441.  
  1442.     tmat = *pimat;
  1443.     tmat.ty -= pcp->y_offset;
  1444.     pdf_set_text_matrix(pdev, &tmat);
  1445.     }
  1446.     pdf_append_chars(pdev, &pcp->char_code, 1);
  1447.     pdev->text.current.x += pcp->x_width * pdev->text.matrix.xx;
  1448.     return 0;
  1449. }
  1450.